﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static FileDialogNative;

namespace FormTest
{
    public class MixedFileDialog : IDisposable
    {
        // 封装CommonOpenFileDialog实例
        private readonly CommonOpenFileDialog _dialog;
        private bool _disposed = false;

        // 暴露常用属性
        public string Title
        {
            get => _dialog.Title;
            set => _dialog.Title = value;
        }

        public bool Multiselect
        {
            get => _dialog.Multiselect;
            set => _dialog.Multiselect = value;
        }

        public string InitialDirectory
        {
            get => _dialog.InitialDirectory;
            set => _dialog.InitialDirectory = value;
        }
        public IEnumerable<string> FileNames => _dialog.FileNames;

        // 构造函数
        public MixedFileDialog()
        {
            _dialog = new CommonOpenFileDialog
            {
                Multiselect = true,
                EnsurePathExists = true,
                AllowNonFileSystemItems = false
            };
        }

        // 显示对话框
        public CommonFileDialogResult ShowDialog1(IWin32Window owner = null)
        {
            // 关键：修改原生对话框选项
            ModifyNativeDialogOptions();
            return _dialog.ShowDialog();
            //return owner != null ? _dialog.ShowDialog(owner) : _dialog.ShowDialog();
        }

        // 直接修改原生IFileDialog的选项
        private void ModifyNativeDialogOptions()
        {
            // 通过反射获取内部的原生对话框实例
            var nativeDialogField = _dialog.GetType().GetField("openDialogCoClass", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

            //var nativeDialogField = _dialog.GetType().GetField(
            //    "_nativeDialog",
            //    System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
            //);

            if (nativeDialogField == null)
                throw new InvalidOperationException("无法访问原生对话框实例");

            var nativeDialog = nativeDialogField.GetValue(_dialog);
            if (nativeDialog == null)
                throw new InvalidOperationException("原生对话框实例为null");

            // 转换为IFileDialog接口并修改选项
            var fileDialog = nativeDialog as IFileDialog;
            if (fileDialog != null)
            {
                fileDialog.GetOptions(out FOS options);

                // 配置混合选择选项
                options |= FOS.FOS_PICKFOLDERS;          // 允许选择目录
                options &= ~FOS.FOS_FILEMUSTEXIST;       // 移除文件必须存在限制
                options &= ~FOS.FOS_STRICTFILETYPES;     // 不严格限制文件类型

                fileDialog.SetOptions(options);
            }
        }


        // 释放资源
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed) return;

            if (disposing)
            {
                // 释放托管资源
                _dialog?.Dispose();
            }

            _disposed = true;
        }

        // 原生IFileDialog接口定义
        [ComImport]
        [Guid("42f85136-db7e-439c-85f1-e4075d135fc8")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IFileDialog
        {
            [PreserveSig]
            int Show(IntPtr parent);
            void SetOptions(FOS fos);
            void GetOptions(out FOS fos);
            // 其他方法定义（保持与原生接口一致）
            void SetFileTypes(uint cFileTypes, IntPtr rgFilterSpec);
            void SetFileTypeIndex(uint iFileType);
            uint GetFileTypeIndex(out uint piFileType);
            void Advise(IntPtr pfde, out uint pdwCookie);
            void Unadvise(uint dwCookie);
            void SetDefaultFolder(IntPtr psi);
            void SetFolder(IntPtr psi);
            void GetFolder(out IntPtr ppsi);
            void GetCurrentSelection(out IntPtr ppsi);
            void SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName);
            void GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
            void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
            void SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText);
            void SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
            void GetResult(out IntPtr ppsi);
            void AddPlace(IntPtr psi, uint fdap);
            void SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
            void Close(int hr);
            void SetClientGuid(ref Guid guid);
            void ClearClientData();
            void SetFilter(object pFilter);
        }

        // FOS枚举定义
        [Flags]
        private enum FOS : uint
        {
            FOS_PICKFOLDERS = 0x20,
            FOS_FILEMUSTEXIST = 0x1000,
            FOS_STRICTFILETYPES = 0x4
        }
    }
}
